import java.io.Serializable; // 导入序列化接口，让对象可以保存到文件
import java.util.Objects; // 导入Objects工具类，用于比较和哈希计算

public class Contact implements Serializable { // 定义联系人类，实现Serializable接口使其可序列化
    private static final long serialVersionUID = 1L; // 序列化版本号，用于版本控制
    private String name, gender, address, phoneNumber, email; // 声明多个字符串变量存储联系人信息
    private int age; // 声明整型变量存储年龄

    public Contact() {
    } // 无参构造函数，创建空的联系人对象

    public Contact(String name, String gender, int age, String address, String phoneNumber) { // 5参数构造函数
        this.name = name;
        this.gender = gender;
        this.age = age;
        this.address = address;
        this.phoneNumber = phoneNumber; // this.变量名指向当前对象的成员变量
    }

    public Contact(String name, String gender, int age, String address, String phoneNumber, String email) { // 6参数构造函数
        this(name, gender, age, address, phoneNumber);
        this.email = email; // this()调用其他构造函数，避免代码重复
    }

    public String getName() {
        return name;
    } // getter方法，返回姓名，public表示可被外部访问

    public String getGender() {
        return gender;
    } // getter方法，返回性别

    public int getAge() {
        return age;
    } // getter方法，返回年龄

    public String getAddress() {
        return address;
    } // getter方法，返回地址

    public String getPhoneNumber() {
        return phoneNumber;
    } // getter方法，返回电话号码

    public String getEmail() {
        return email;
    } // getter方法，返回邮箱

    public void setName(String name) { // setter方法，设置姓名，void表示无返回值
        if (name == null || name.trim().isEmpty())
            throw new IllegalArgumentException("姓名不能为空"); // 数据验证，trim()去除前后空格
        this.name = name.trim(); // 设置姓名，去除前后空格
    }

    public void setGender(String gender) { // setter方法，设置性别
        if (gender == null || (!gender.equals("男") && !gender.equals("女")))
            throw new IllegalArgumentException("性别只能是'男'或'女'"); // 验证性别只能是男或女
        this.gender = gender; // 设置性别
    }

    public void setAge(int age) { // setter方法，设置年龄
        if (age < 0 || age > 150)
            throw new IllegalArgumentException("年龄必须在0-150之间"); // 验证年龄范围
        this.age = age; // 设置年龄
    }

    public void setAddress(String address) {
        this.address = address;
    } // setter方法，设置地址，地址可以为空所以不验证

    public void setPhoneNumber(String phoneNumber) { // setter方法，设置电话号码
        if (phoneNumber == null || phoneNumber.trim().isEmpty())
            throw new IllegalArgumentException("联系方式不能为空"); // 验证电话不能为空
        this.phoneNumber = phoneNumber.trim(); // 设置电话，去除前后空格
    }

    public void setEmail(String email) {
        this.email = email;
    } // setter方法，设置邮箱，邮箱可以为空

    public boolean isValid() { // 验证联系人信息是否完整有效
        return name != null && !name.trim().isEmpty() && gender != null && // 检查姓名和性别不为空
                (gender.equals("男") || gender.equals("女")) && age >= 0 && age <= 150 && // 检查性别有效且年龄在范围内
                phoneNumber != null && !phoneNumber.trim().isEmpty(); // 检查电话不为空
    }

    @Override // 注解表示重写父类方法
    public boolean equals(Object obj) { // 重写equals方法，用于比较两个对象是否相等
        if (this == obj)
            return true; // 如果是同一个对象引用，直接返回true
        if (obj == null || getClass() != obj.getClass())
            return false; // 如果对象为null或类型不同，返回false
        Contact contact = (Contact) obj; // 将Object类型转换为Contact类型
        return age == contact.age && Objects.equals(name, contact.name) && Objects.equals(gender, contact.gender) && // 比较年龄和字符串字段
                Objects.equals(address, contact.address) && Objects.equals(phoneNumber, contact.phoneNumber)
                && Objects.equals(email, contact.email); // Objects.equals可以安全比较可能为null的字符串
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, gender, age, address, phoneNumber, email);
    } // 重写hashCode方法，基于所有字段生成哈希值

    @Override
    public String toString() { // 重写toString方法，将对象转换为字符串表示
        return String.format("姓名: %s, 性别: %s, 年龄: %d, 地址: %s, 电话: %s%s", name, gender, age, // String.format格式化字符串，%s表示字符串，%d表示整数
                address != null ? address : "未填写", phoneNumber, email != null ? ", 邮箱: " + email : ""); // 三元运算符：条件 ? 值1
                                                                                                        // : 值2
    }
}